using System.IO;
using System.Reflection;
using HttpServer.Sessions;
using Microsoft.Security.Application;
using Spark;

namespace HttpServer.MVC.Rendering.Spark
{
    /// <summary>
    /// The SparkView class holds information needed to render the model to HTML.
    /// </summary>
    /// <remarks>
    /// This is a stripped-down version of the SparkView written by 
    /// Louis DeJardin (http://whereslou.com) in his Spark.Web.Mvc project.
    /// It removes dependencies on System.Web.Mvc and Spark.Web.Mvc.
    /// It also replaces the System.Web HttpUtility.HtmlEncode method with
    /// one provided by the Microsoft AntiXSS library.
    /// </remarks>
    public abstract class SparkView : AbstractSparkView
    {
        private string _SiteRoot;
        private SparkDataDictionary _ViewData;



        public IHttpRequest Request { get; set; }

        public IHttpResponse Response { get; set; }

        public IHttpSession Session { get; set; }


        public IResourcePathManager ResourcePathManager { get; set; }

        public override bool TryGetViewData(string name, out object value)
        {
            if (ViewData.ContainsKey(name))
            {
                value = ViewData[name];
                return true;
            }
            if (ViewData.Model != null)
            {
                var property = ViewData.Model.GetType().GetProperty(name);
                if (property != null)
                {
                    value = property.GetValue(ViewData.Model, null);
                    return true;
                }
            }
            value = null;
            return false;
        }

        public string SiteRoot
        {
            get
            {
                if (_SiteRoot == null)
                {
                    //var appPath = ViewContext.HttpContext.Request.ApplicationPath;
                    var appPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); // DTHRASHER 8DEC2009
                    if (string.IsNullOrEmpty(appPath) || string.Equals(appPath, "/"))
                    {
                        _SiteRoot = string.Empty;
                    }
                    else
                    {
                        _SiteRoot = "/" + appPath.Trim('/');
                    }
                }
                return _SiteRoot;
            }
        }
        public string SiteResource(string path)
        {
            return ResourcePathManager.GetResourcePath(SiteRoot, path);
        }

        //#region IView Members

        //public void Render(ViewContext viewContext, TextWriter writer)
        //{
        //    var wrappedHttpContext = new HttpContextWrapper(viewContext.HttpContext, this);

        //    var wrappedViewContext = new ViewContext(
        //        new ControllerContext(wrappedHttpContext, viewContext.RouteData, viewContext.Controller),
        //        viewContext.View,
        //        viewContext.ViewData,
        //        viewContext.TempData);

        //    ViewContext = wrappedViewContext;
        //    ViewData = wrappedViewContext.ViewData;
        //    Html = new HtmlHelper(wrappedViewContext, this);
        //    Url = new UrlHelper(wrappedViewContext.RequestContext);
        //    Ajax = new AjaxHelper(wrappedViewContext, this);

        //    var outerView = ViewContext.View as SparkView;
        //    var isNestedView = outerView != null && ReferenceEquals(this, outerView) == false;

        //    var priorContent = _content;
        //    var priorOnce = _once;
        //    TextWriter priorContentView = null;

        //    if (isNestedView)
        //    {
        //        // set aside the "view" content, to avoid modification
        //        if (outerView._content.TryGetValue("view", out priorContentView))
        //            outerView._content.Remove("view");

        //        // assume the values of the outer view collections
        //        _content = outerView._content;
        //        _once = outerView._once;
        //    }

        //    RenderView(writer);

        //    if (isNestedView)
        //    {
        //        _content = priorContent;
        //        _once = priorOnce;

        //        // restore previous state of "view" content
        //        if (priorContentView != null)
        //            outerView._content["view"] = priorContentView;
        //        else if (outerView._content.ContainsKey("view"))
        //            outerView._content.Remove("view");
        //    }
        //    else
        //    {
        //        // proactively dispose named content. pools spoolwriter pages. avoids finalizers.
        //        foreach (var content in Content.Values)
        //            content.Close();
        //    }

        //    Content.Clear();
        //}

        //#endregion

        //#region IViewDataContainer Members

        public SparkDataDictionary ViewData
        {
            get
            {
                if (_ViewData == null)
                    SetViewData(new SparkDataDictionary());
                return _ViewData;
            }
            set { SetViewData(value); }
        }

        //#endregion

        /// <summary>
        /// Converts the <paramref name="value"/> to a string and encodes it 
        /// for HTML using the Microsoft AntiXSS library. 
        /// </summary>
        /// <param name="value">The object to HtmlEncode.</param>
        /// <returns>A string that can be safely displayed on an HTML page.</returns>
        public string H(object value)
        {
            return AntiXss.HtmlEncode(value.ToString());
        }

        public object Eval(string expression)
        {
            return ViewData.Eval(expression);
        }
        public string Eval(string expression, string format)
        {
            return ViewData.Eval(expression, format);
        }

        protected virtual void SetViewData(SparkDataDictionary viewData)
        {
            _ViewData = viewData;
        }
    }

}
